<template>
  <div class="app-container">
    <div class="filter-container">
      <el-button
        v-if="checkPermission(['AbpIdentity.Roles.Create'])"
        class="filter-item"
        style="margin-left: 10px;"
        type="primary"
        icon="el-icon-edit"
        @click="handleCreate"
      >添加</el-button>
      <el-button
        v-if="false"
        v-waves
        :loading="downloadLoading"
        class="filter-item"
        type="primary"
        icon="el-icon-download"
        @click="handleDownload"
      >导出</el-button>
    </div>

    <el-table
      :key="tableKey"
      v-loading="listLoading"
      style="width: 100%"
      :data="list"
    >
      <el-table-column label="名称" width="180px" align="center">
        <template slot-scope="scope">
          <span>{{ scope.row.name }}</span>
        </template>
      </el-table-column>
      <el-table-column label="默认" width="150px" align="center">
        <template slot-scope="scope">
          <span>{{ scope.row.isDefault | booleanParse }}</span>
        </template>
      </el-table-column>
      <el-table-column label="公开" width="150px" align="center">
        <template slot-scope="scope">
          <span>{{ scope.row.isPublic | booleanParse }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        width="230"
        class-name="small-padding fixed-width"
      >
        <template slot-scope="{row}">
          <el-button v-if="checkPermission(['AbpIdentity.Roles.Update'])" type="primary" size="mini" icon="el-icon-edit" @click="handleUpdate(row)">编辑</el-button>
          <el-button v-if="checkPermission(['AbpIdentity.Roles.Delete']) || row.isStatic===false" size="mini" type="danger" icon="el-icon-delete" @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="temp"
        label-position="right"
        label-width="150px"
        style="width: 400px; margin-left:50px;"
      >
        <el-form-item label="名称" prop="name">
          <el-input v-model="temp.name" />
        </el-form-item>
        <el-form-item label="默认">
          <el-switch v-model="temp.isDefault" active-color="#13ce66" inactive-color="#dcdfe6" />
        </el-form-item>
        <el-form-item label="公开">
          <el-switch v-model="temp.isPublic" active-color="#13ce66" inactive-color="#dcdfe6" />
        </el-form-item>
        <el-form-item label="权限">
          <el-tree
            ref="tree"
            :data="temp.permissions"
            :props="defaultProps"
            check-directly
            show-checkbox
            node-key="name"
            class="permission-tree"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button :loading="loading" type="primary" @click="dialogStatus==='create'?createData():updateData()">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getPermissions, updatePermissions } from '@/api/permission'
import { getRoles, getRole, createRole, updateRole, deleteRole } from '@/api/role'
import waves from '@/directive/waves' // waves directive
import { booleanParse } from '@/utils/dictionary'
import checkPermission from '@/utils/permission' // 权限判断函数

export default {
  name: 'Role',
  components: { },
  filters: {
    booleanParse
  },
  directives: { waves },
  data() {
    return {
      tableKey: 0,
      list: null,
      permissions: [],
      listLoading: true,
      defaultProps: {
        children: 'children',
        label: 'title'
      },
      temp: {
        id: '',
        name: '',
        isDefault: false,
        isPublic: true,
        concurrencyStamp: '',
        permissions: []
      },
      dialogFormVisible: false,
      dialogStatus: '',
      textMap: {
        update: '编辑角色',
        create: '添加角色'
      },
      rules: {
        userName: [{ required: true, message: '角色名必须填写', trigger: 'blur' }]
      },
      downloadLoading: false,
      loading: false
    }
  },
  created() {
    this.getList()

    const params = {
      providerName: 'R',
      providerKey: 'admin'
    }
    // 查找所有的权限
    getPermissions(params).then(response => {
      const { data } = response
      const treeData = this.generatePermissions(data.groups)
      this.permissions = treeData
    })
  },
  methods: {
    checkPermission,
    getList() {
      this.listLoading = true
      getRoles().then(response => {
        const { data } = response
        const roles = data.items.map(v => {
          return { key: v.name, display_name: v.name }
        })
        this.roleOptions = roles

        this.list = data.items
        this.listLoading = false
      })
    },
    resetTemp() {
      const _self = this
      this.temp = {
        id: '',
        name: '',
        isDefault: false,
        isPublic: true,
        concurrencyStamp: '',
        permissions: _self.permissions
      }
    },
    handleCreate() {
      this.resetTemp()
      if (this.$refs.tree) {
        this.$refs.tree.setCheckedNodes([])
      }
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    createData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          this.loading = true
          createRole(this.temp).then(() => {
            this.submitPermission()
            this.getList()
            this.dialogFormVisible = false
            this.$notify({
              title: '成功',
              message: '添加角色成功',
              type: 'success',
              duration: 2000
            })
          }).catch(err => {
            console.log(err)
          }).finally(() => {
            this.loading = false
          })
        }
      })
    },
    handleUpdate(row) {
      const { id } = row
      getRole(id).then(response => {
        this.temp.id = response.data.id
        this.temp.concurrencyStamp = response.data.concurrencyStamp
        this.temp.name = response.data.name // copy obj
        this.temp.isDefault = response.data.isDefault // copy obj
        this.temp.isPublic = response.data.isPublic // copy obj
        this.temp.permissions = this.permissions
        if (this.$refs.tree) {
          this.$refs.tree.setCheckedNodes([])
        }
        this.dialogStatus = 'update'
        this.dialogFormVisible = true
        const params = {
          providerName: 'R',
          providerKey: response.data.name
        }
        getPermissions(params).then(response => {
          const { data } = response
          const treeSelectKeys = this.getPermissionKeys(data.groups)
          this.$refs.tree.setCheckedKeys(treeSelectKeys)
        })
        this.$nextTick(() => {
          this.$refs['dataForm'].clearValidate()
        })
      })
    },
    updateData() {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          this.loading = true
          const id = this.temp.id
          const data = {
            name: this.temp.name,
            isDefault: this.temp.isDefault,
            isPublic: this.temp.isPublic,
            concurrencyStamp: this.temp.concurrencyStamp
          }
          updateRole(id, data).then(() => {
            this.submitPermission()
            this.getList()
            this.dialogFormVisible = false
            this.$notify({
              title: '成功',
              message: '修改成功',
              type: 'success',
              duration: 2000
            })
          }).finally(() => {
            this.loading = false
          })
        }
      })
    },
    handleDelete(row) {
      this.$confirm('此操作将删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        center: true
      }).then(() => {
        const { id } = row
        deleteRole(id).then(() => {
          this.$notify({
            title: '成功',
            message: '删除成功',
            type: 'success',
            duration: 2000
          })
          this.getList()
        })
      }).catch(err => {
        console.log(err)
      })
    },
    handleDownload() {
      this.downloadLoading = true
      import('@/vendor/Export2Excel').then(excel => {
        const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
        const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
        const data = this.formatJson(filterVal, this.list)
        excel.export_json_to_excel({
          header: tHeader,
          data,
          filename: 'table-list'
        })
        this.downloadLoading = false
      })
    },
    generatePermissions(groups) {
      var newObj = []
      groups.forEach(group => {
        const { permissions } = group
        var parentNames = permissions.filter(item => item.parentName === null)
        parentNames.forEach(item => {
          var treeData = {
            title: item.displayName,
            expand: true,
            name: item.name,
            checked: item.isGranted,
            children: []
          }

          newObj.push(treeData)

          var childrens = permissions.filter(it => it.parentName === item.name)

          if (childrens && childrens.length > 0) {
            this.generateTreeNode(permissions, treeData)
          }
        })
      })

      return newObj
    },
    generateTreeNode(permissions, parentNode) {
      var parentNames = permissions.filter(item => item.parentName === parentNode.name)
      parentNames.forEach(item => {
        var treeData = {
          title: item.displayName,
          expand: true,
          name: item.name,
          checked: item.isGranted,
          children: []
        }

        var childrens = permissions.filter(it => it.parentName === item.name)

        if (childrens && childrens.length > 0) {
          this.generateTreeNode(permissions, treeData)
        }

        parentNode.children.push(treeData)
      })
    },
    getPermissionKeys(groups) {
      // 获取权限key
      var newObj = []
      groups.forEach(group => {
        const { permissions } = group
        var parentNames = permissions.filter(item => item.parentName === null)
        parentNames.forEach(item => {
          if (item.isGranted) {
            newObj.push(item.name)
          }
          var childrens = permissions.filter(it => it.parentName === item.name)
          childrens.forEach(r => {
            if (r.isGranted) {
              newObj.push(r.name)
            }
          })
        })
      })

      return newObj
    },
    submitPermission() {
      const _self = this
      return new Promise((resolve, reject) => {
        var permissions = []

        const allowPermissions = _self.$refs.tree.getCheckedKeys()
        
        _self.temp.permissions.forEach(r => {
          if (allowPermissions.includes(r.name)) {
            permissions.push({
              name: r.name,
              isGranted: true
            })
          } else {
            permissions.push({
              name: r.name,
              isGranted: false
            })
          }
          r.children.forEach(p1 => {
            if (allowPermissions.includes(p1.name)) {
              permissions.push({
                name: p1.name,
                isGranted: true
              })
            } else {
              permissions.push({
                name: p1.name,
                isGranted: false
              })
            }
            p1.children.forEach(p2 => {
              if (allowPermissions.includes(p2.name)) {
                permissions.push({
                  name: p2.name,
                  isGranted: true
                })
              } else {
                permissions.push({
                  name: p2.name,
                  isGranted: false
                })
              }
            })
          })
        })

        const params = {
          providerName: 'R',
          providerKey: _self.temp.name
        }
        updatePermissions(params, {
          permissions: permissions
        }).then(res => {
          resolve(true)
        }).catch(err => {
          console.log(err)
          reject(false)
        })
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.app-container {
  .roles-table {
    margin-top: 30px;
  }
  .permission-tree {
    margin-bottom: 30px;
  }
}
</style>
